package org.jeecg.modules.ws.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import jodd.util.StringUtil;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.modules.ws.common.WsFileEnum;
import org.jeecg.modules.ws.entity.WsFile;
import org.jeecg.modules.ws.mapper.WsFileMapper;
import org.jeecg.modules.ws.service.IWsFileService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @Description: 附件信息
 * @Author: jeecg-boot
 * @Date: 2025-04-21
 * @Version: V1.0
 */
@Service
public class WsFileServiceImpl extends ServiceImpl<WsFileMapper, WsFile> implements IWsFileService {
    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public WsFile uploadFile(MultipartFile mf, String bizName, String bizTableId, String bizFieldName) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        StringBuilder bizPath = new StringBuilder();
        bizPath.append(uploadpath).append(File.separator).append(bizName).append(File.separator).append(bizTableId).append(File.separator);
        if (StringUtil.isNotBlank(bizFieldName)) {
            bizPath.append(bizFieldName).append(File.separator);
        }
        String filePath = bizPath.toString();
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();// 创建文件根目录
        }
        String fileName = mf.getOriginalFilename();
        String savePath = file.getPath() + File.separator + fileName;
        File savefile = new File(savePath);
        FileCopyUtils.copy(mf.getBytes(), savefile);
        // 保存文件记录数据
        String dbpath = savePath;
        if (dbpath.contains("\\")) {
            dbpath = dbpath.replace("\\", "/");
        }
        long size = mf.getSize();
        WsFile fileEntity = new WsFile();
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (loginUser != null) {
            fileEntity.setUploadBy(loginUser.getUsername());
        }
        fileEntity.setUploadTime(new Date());
        fileEntity.setFileName(fileName);
        fileEntity.setFilePath(dbpath);
        fileEntity.setFileSize(size);
        fileEntity.setBizName(bizName);
        fileEntity.setBizTableId(bizTableId);
        fileEntity.setBizFieldName(bizFieldName);
        LambdaQueryWrapper<WsFile> query = Wrappers.lambdaQuery(WsFile.class);
        query.eq(WsFile::getBizName, bizName).eq(WsFile::getBizTableId, bizTableId).eq(WsFile::getFileName, fileName);
        if (StringUtil.isNotBlank(bizFieldName)) {
            query.eq(WsFile::getBizFieldName, bizFieldName);
        }
        saveOrUpdate(fileEntity, query);
        // 保存文件地址到对应业务表中
        WsFileEnum fileEnum = WsFileEnum.getByBizName(bizName);
        if (fileEnum != null) {
            IService<?> iService = (IService<?>) SpringContextUtils.getBean(fileEnum.getBizClass());
            Object object = iService.getById(bizTableId);
            if (object != null) {
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(object));
                jsonObject.put(fileEnum.getBizFieldName(), dbpath);

                // 将 JSONObject 转换回实体对象
                Class<?> entityClass = iService.getEntityClass();
                Object updatedObject = JSON.parseObject(jsonObject.toJSONString(), entityClass);

                // 调用 updateById 方法更新数据库
                Method method = iService.getClass().getDeclaredMethod("updateById", Object.class);
                method.setAccessible(true);
                method.invoke(iService, updatedObject);
            }
        }
        return fileEntity;
    }

    @Override
    public void deleteFile(String id) throws Exception {
        WsFile wsFile = this.getById(id);
        if (wsFile != null) {
            this.removeById(id);
            String bizName = wsFile.getBizName();
            String bizTableId = wsFile.getBizTableId();
            WsFileEnum fileEnum = WsFileEnum.getByBizName(bizName);
            if (fileEnum != null) {
                IService<?> iService = (IService<?>) SpringContextUtils.getBean(fileEnum.getBizClass());
                Object object = iService.getById(bizTableId);
                if (object != null) {
                    JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(object));
                    jsonObject.put(fileEnum.getBizFieldName(), "");
                    Class<?> entityClass = iService.getEntityClass();
                    Object updatedObject = JSON.parseObject(jsonObject.toJSONString(), entityClass);
                    // 调用 updateById 方法更新数据库
                    Method method = iService.getClass().getDeclaredMethod("updateById", Object.class);
                    method.setAccessible(true);
                    method.invoke(iService, updatedObject);
                }
            }
            File file = new File(wsFile.getFilePath());
            if (file.exists()) {
                file.delete();
            }
        }
    }

    /*@Override
    public File download(String bizTableId) {
        StringBuilder bizPath = new StringBuilder();
        bizPath.append(uploadpath).append(File.separator).append(bizName).append(File.separator).append(bizTableId).append(File.separator);
        if (StringUtil.isNotBlank(bizFieldName)){
            bizPath.append(bizFieldName).append(File.separator);
        }
        bizPath.append(fileName);
        WsFile wsFile = this.getById(bizTableId);
        String filePath = wsFile.getFilePath();
        return new File(filePath);
    }*/
}
